/*
 * 项目名称:    wms-server-jeecg
 * 创建人员:    hansen
 * 创建时间:    2023-09-20
 */
package org.jeecg.modules.dock.handler.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.FillRuleUtil;
import org.jeecg.modules.basic.material.entity.BasicMaterial;
import org.jeecg.modules.basic.material.service.IBasicMaterialService;
import org.jeecg.modules.basic.plant.service.IWmsSapWarehouseMapService;
import org.jeecg.modules.basic.unit.entity.BasicUnit;
import org.jeecg.modules.basic.unit.service.IBasicUnitService;
import org.jeecg.modules.business.doc.business.vo.WarehousingStrategyOneParamVO;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTaskMaterial;
import org.jeecg.modules.business.outbound.vo.WmsOutReceiptTaskPage;
import org.jeecg.modules.business.warehouse.entity.WmsInReceiptTaskMaterial;
import org.jeecg.modules.business.warehouse.entity.vo.WmsInReceiptTaskPage;
import org.jeecg.modules.dock.constant.SystemConstants;
import org.jeecg.modules.dock.entity.dto.request.UBShipmentsRequestDTO;
import org.jeecg.modules.dock.entity.dto.response.SapBaseResponseDTO;
import org.jeecg.modules.dock.enums.DirectionOfInventoryEnum;
import org.jeecg.modules.dock.enums.DockDataStatus;
import org.jeecg.modules.dock.enums.ReceiptsEnum;
import org.jeecg.modules.dock.enums.SapInterfaceTypeEnum;
import org.jeecg.modules.dock.handler.AbstractSapDataHandler;
import org.jeecg.modules.flow.sys.entity.dto.BaseFlowDto;
import org.jeecg.modules.flow.sys.service.WorkFlowService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 结构件/夹件UB单发货handler
 *
 * @author hansen
 * @version 1.0.0
 * @date 2023-09-20 15:23:53
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class UBShipmentsHandler extends AbstractSapDataHandler<UBShipmentsRequestDTO> {

    private final WorkFlowService workFlowService;
    private final IBasicMaterialService materialService;
    private final SapCommonService sapCommonService;
    private final IWmsSapWarehouseMapService wmsSapWarehouseMapService;
    private final IBasicUnitService iBasicUnitService;
    @Value(value = "${wms.config.personnel.sap:}")
    private String personnelSap;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public synchronized List<? extends SapBaseResponseDTO> doHandle(List<UBShipmentsRequestDTO> data) {
        List<SapBaseResponseDTO> dtoList = new ArrayList<>(16);
        SapBaseResponseDTO responseDTO = new SapBaseResponseDTO();
        log.info("收到结构件/夹件UB单发货:{},\n共{}条", data, data.size());
        if (CollectionUtil.isNotEmpty(data)) {

            List<String> materialCodes = data.stream().map(t -> t.getMateriel()).collect(Collectors.toList());
            sapCommonService.verifyExistenceMaterialCode(materialCodes);

            Map<String, List<UBShipmentsRequestDTO>> outCollect = data.stream().collect(Collectors.groupingBy(UBShipmentsRequestDTO::getDepartureDepot));
            log.info("出库任务分组结果: {}", outCollect);
            Set<String> outKey = outCollect.keySet();
            for (int i = 0; i < outKey.size(); i++) {
                String sapLocation = outKey.iterator().next();
                List<UBShipmentsRequestDTO> outDto = outCollect.get(sapLocation);
                List<WmsOutReceiptTaskMaterial> outList = new ArrayList<>();
                for (UBShipmentsRequestDTO dto : outDto) {
                    WarehousingStrategyOneParamVO vo = new WarehousingStrategyOneParamVO();
                    WmsOutReceiptTaskMaterial outMaterial = new WmsOutReceiptTaskMaterial();
                    outMaterial.setSysOrgCode("A04A01");
                    outMaterial.setSaleOrderNumber(dto.getSaleOrderCode());
                    outMaterial.setSaleOrderLineNumber(dto.getSaleOrderCodeLine());
                    outMaterial.setOriginalSystemNumber(dto.getUbDumpNumber());
                    outMaterial.setOriginalSystemLineNumber(dto.getUbLineProject());
                    outMaterial.setExtraText(JSON.toJSONString(dto));
                    BasicUnit unit = iBasicUnitService.getOne(new LambdaQueryWrapper<BasicUnit>()
                            .eq(BasicUnit::getCode, dto.getUnit()));
                    if (ObjectUtil.isNotEmpty(unit)) {
                        outMaterial.setWmsBasicUnitId(unit.getId());
                    }
                    if (ObjectUtil.isNotNull(dto.getNumber())) {
                        outMaterial.setPlanQuantity(dto.getNumber());
                    }
                    List<BasicMaterial> basicMaterials = materialService.listByCode(dto.getMateriel());
                    
                    String wmsBasicWarehouseId = wmsSapWarehouseMapService.getWmsStroeBySapStore(sapLocation,dto.getFactory());
                    outMaterial.setWmsBasicWarehouseId(wmsBasicWarehouseId);
                    if (wmsBasicWarehouseId == null){
                        outMaterial.setSapLocationFactory(sapLocation+"-"+dto.getFactory());
                        outMaterial.setWmsBasicWarehouseId("");
                    }
                    if (CollectionUtil.isNotEmpty(basicMaterials)) {
                        BasicMaterial basicMaterial = basicMaterials.get(0);
                        outMaterial.setWmsBasicMaterialId(basicMaterial.getId());
                        vo.setMaterialId(basicMaterial.getId());
                        if (StringUtils.isNotEmpty(basicMaterial.getAssistantUnitId())) {
                            outMaterial.setUnitAssistId(basicMaterial.getAssistantUnitId());
                            outMaterial.setAssistQuantity(BigDecimal.ONE);
                        }
                    }
                    vo.setDocumentType(ReceiptsEnum.R43.getCode());

                    outList.add(outMaterial);
                }
                WmsOutReceiptTaskPage wmsOutReceiptTaskPage = new WmsOutReceiptTaskPage();
                wmsOutReceiptTaskPage.setOrganization("A04A01");
                wmsOutReceiptTaskPage.setDocumentType(ReceiptsEnum.C42.getCode());
                wmsOutReceiptTaskPage.setSysOrgCode("A04A01");
                wmsOutReceiptTaskPage.setOwnerType("1");
                wmsOutReceiptTaskPage.setOwner("A05");
                wmsOutReceiptTaskPage.setWmsOutReceiptTaskMaterialList(outList);
                wmsOutReceiptTaskPage.setOriginalSystem(SystemConstants.SAP);
                wmsOutReceiptTaskPage.setRequestTime(DateUtil.formatTime(new Date()));
                wmsOutReceiptTaskPage.setRequestPerson(DirectionOfInventoryEnum.OUTBOUND.getSource());
                wmsOutReceiptTaskPage.setCreateBy(personnelSap);
                wmsOutReceiptTaskPage.setDocumentCode(FillRuleUtil.executeRule(DirectionOfInventoryEnum.OUTBOUND.getCode(), JSON.parseObject(DirectionOfInventoryEnum.OUTBOUND.getRemark())).toString());
                wmsOutReceiptTaskPage.setTaskDate(DateUtil.parseDate(DateUtil.now()));

                if (CollectionUtil.isNotEmpty(wmsOutReceiptTaskPage.getWmsOutReceiptTaskMaterialList())) {
                    WmsOutReceiptTaskMaterial taskMaterial = wmsOutReceiptTaskPage.getWmsOutReceiptTaskMaterialList().get(0);
                    wmsOutReceiptTaskPage.setOriginalSystemNumber(taskMaterial.getOriginalSystemNumber());
                }

                BaseFlowDto outFlow = new BaseFlowDto();
                outFlow.setBusinessType(ReceiptsEnum.C42.getType());
                outFlow.setDocumentType(ReceiptsEnum.C42.getCode());
                outFlow.setCode(ReceiptsEnum.C42.getRemark());
                outFlow.setData(wmsOutReceiptTaskPage);

                try {
                    workFlowService.commit(outFlow);
                    responseDTO.setResult(DockDataStatus.SUCCESS.getCode());
                    responseDTO.setUuid(data.get(0).getUuid());
                } catch (Exception e) {
                    responseDTO.setResult(DockDataStatus.FAILURE.getCode());
                    responseDTO.setUuid(data.get(0).getUuid());
                    responseDTO.setMessage("生成结构件/夹件UB出库任务异常");
                    throw new JeecgBootException("结构件/夹件UB单发货: {}", e);
                }
                log.info("sap库位为: {}" + "的出库任务已创建", sapLocation);
            }

            Map<String, List<UBShipmentsRequestDTO>> inCollect = data.stream().collect(Collectors.groupingBy(UBShipmentsRequestDTO::getReceivingLocation));
            log.info("入库任务分组结果: {}", inCollect);
            Set<String> inKey = inCollect.keySet();
            for (int i = 0; i < inKey.size(); i++) {
                String sapLocation = inKey.iterator().next();
                List<UBShipmentsRequestDTO> inDto = inCollect.get(sapLocation);
                ArrayList<WmsInReceiptTaskMaterial> inReceiptTaskMaterials = new ArrayList<>();

                Map<String, String> unitIdMap = new HashMap<>();
                if (CollectionUtil.isNotEmpty(inDto)) {
                    List<String> codes = inDto.stream().map(t -> t.getUnit()).collect(Collectors.toList());
                    unitIdMap = iBasicUnitService.getIdByCodes(codes);
                }

                for (UBShipmentsRequestDTO dto : inDto) {
                    WmsInReceiptTaskMaterial wmsInReceiptTaskMaterial = new WmsInReceiptTaskMaterial();
                    wmsInReceiptTaskMaterial.setSysOrgCode("A04A01");
                    BasicUnit unit = iBasicUnitService.getOne(new LambdaQueryWrapper<BasicUnit>()
                            .eq(BasicUnit::getCode, dto.getUnit()));
                    if (ObjectUtil.isNotEmpty(unit)) {
                        wmsInReceiptTaskMaterial.setUnitAssistId(unit.getId());
                    }
                    wmsInReceiptTaskMaterial.setSaleOrderNumber(dto.getSaleOrderCode());
                    wmsInReceiptTaskMaterial.setSaleOrderLineNumber(dto.getSaleOrderCodeLine());
                    wmsInReceiptTaskMaterial.setOriginalSystemNumber(dto.getUbDumpNumber());
                    wmsInReceiptTaskMaterial.setOriginalSystemLineNumber(dto.getUbLineProject());
                    wmsInReceiptTaskMaterial.setExtraText(JSON.toJSONString(dto));
                    wmsInReceiptTaskMaterial.setWmsBasicUnitId(ObjectUtil.isNotEmpty(unitIdMap.get(dto.getUnit())) ? unitIdMap.get(dto.getUnit()) : "");
                    wmsInReceiptTaskMaterial.setPlanQuantity(dto.getNumber());
                    wmsInReceiptTaskMaterial.setFactory(dto.getFactory());
                    List<BasicMaterial> basicMaterials = materialService.listByCode(dto.getMateriel());

                    String wmsBasicWarehouseId = wmsSapWarehouseMapService.getWmsStroeBySapStore(sapLocation,dto.getFactory());
                    wmsInReceiptTaskMaterial.setWmsBasicWarehouseId(wmsBasicWarehouseId);
                    if (wmsBasicWarehouseId == null){
                        wmsInReceiptTaskMaterial.setSapLocationFactory(sapLocation+"-"+dto.getFactory());
                        wmsInReceiptTaskMaterial.setWmsBasicWarehouseId("");
                    }
                    wmsInReceiptTaskMaterial.setSapLocation(sapLocation);
                    if (CollectionUtil.isNotEmpty(basicMaterials)) {
                        BasicMaterial basicMaterial = basicMaterials.get(0);
                        wmsInReceiptTaskMaterial.setWmsBasicMaterialId(basicMaterial.getId());
                        if (StringUtils.isNotEmpty(basicMaterial.getAssistantUnitId())) {
                            wmsInReceiptTaskMaterial.setUnitAssistId(basicMaterial.getAssistantUnitId());
                            wmsInReceiptTaskMaterial.setAssistQuantity(BigDecimal.ONE);
                        }
                    }
                    inReceiptTaskMaterials.add(wmsInReceiptTaskMaterial);
                }
                WmsInReceiptTaskPage wmsInReceiptTaskPage = new WmsInReceiptTaskPage();
                wmsInReceiptTaskPage.setOrganization("A04A01");
                wmsInReceiptTaskPage.setDocumentType(ReceiptsEnum.R43.getCode());
                wmsInReceiptTaskPage.setSysOrgCode("A04A01");
                wmsInReceiptTaskPage.setOwnerType("1");
                wmsInReceiptTaskPage.setOwner("A05");
                wmsInReceiptTaskPage.setOriginalSystem(SystemConstants.SAP);
                wmsInReceiptTaskPage.setRequestTime(new Date());
                wmsInReceiptTaskPage.setWmsInReceiptTaskMaterialList(inReceiptTaskMaterials);
                wmsInReceiptTaskPage.setDocumentCode(FillRuleUtil.executeRule(DirectionOfInventoryEnum.STORAGE.getCode(), JSON.parseObject(DirectionOfInventoryEnum.STORAGE.getRemark())).toString());
                wmsInReceiptTaskPage.setTaskDate(new Date());
                wmsInReceiptTaskPage.setRequestPerson(DirectionOfInventoryEnum.STORAGE.getSource());
                wmsInReceiptTaskPage.setCreateBy(personnelSap);

                if (CollectionUtil.isNotEmpty(wmsInReceiptTaskPage.getWmsInReceiptTaskMaterialList())) {
                    WmsInReceiptTaskMaterial taskMaterial = wmsInReceiptTaskPage.getWmsInReceiptTaskMaterialList().get(0);
                    wmsInReceiptTaskPage.setOriginalSystemNumber(taskMaterial.getOriginalSystemNumber());
                }

                BaseFlowDto baseFlowDto = new BaseFlowDto();
                baseFlowDto.setBusinessType(ReceiptsEnum.R43.getType());
                baseFlowDto.setDocumentType(ReceiptsEnum.R43.getCode());
                baseFlowDto.setCode(ReceiptsEnum.R43.getRemark());
                baseFlowDto.setData(wmsInReceiptTaskPage);
                try {
                    workFlowService.commit(baseFlowDto);
                    responseDTO.setResult(DockDataStatus.SUCCESS.getCode());
                    responseDTO.setUuid(data.get(0).getUuid());
                } catch (Exception e) {
                    responseDTO.setResult(DockDataStatus.FAILURE.getCode());
                    responseDTO.setUuid(data.get(0).getUuid());
                    responseDTO.setMessage("生成结构件/夹件UB入库任务异常");
                    throw new JeecgBootException("结构件/夹件UB单发货: {}", e);
                }
                log.info("sap库位为: {}" + "的入库任务已创建", sapLocation);
            }
            dtoList.add(responseDTO);
        }
        return dtoList;
    }

    @Override
    public SapInterfaceTypeEnum type() {
        return SapInterfaceTypeEnum.STRUCT_AND_CLIPS_UB_SEND;
    }
}
